function MapManager(){
		    
    var markerMgr = new MarkerManager();
    var map = new GMap2(document.getElementById("map_canvas"),{mapTypes : [G_NORMAL_MAP,G_PHYSICAL_MAP,G_SATELLITE_MAP]});
    map.enableRotation();
    var userPosition;
    	
   
    $.fn.getMarkerMgr = function()
    {
    	return markerMgr;
    };
    
    $.fn.getUserPosition = function()
    {
    	return userPosition;
    }
    	
    $.fn.getUserMap = function ()
    {
    	return map;
    }
    
    $.fn.isGearInstalled = function(){
		return (window.google && google.gears);
	};
			
	$.fn.initUserMap = function (){
	
		if(this.isGearInstalled()){
			var geo = google.gears.factory.create('beta.geolocation');
			geo.getCurrentPosition(this.overlayUserSpot, function(error){});
		}else
		{
			var userLocation = google.loader.ClientLocation;
			this.overlayUserSpot({latitude: userLocation.latitude, longitude: userLocation.longitude});
		}
				
	};
	
	
	
	$.fn.changeUserLocation = function(address)
	{
		var geocoder = new GClientGeocoder();
		
		geocoder.getLatLng( address,
				function(point) {
			        if (!point) {
			        	var dialogMgr = new DialogManager();
			        	$(dialogMgr).showDialog({id:"changeLocWarn", height:"100", width:"400"});
			        } else {
			        	$(markerMgr).removeMarker("user");
			        	 $.fn.overlayUserSpot({latitude: point.lat(), longitude: point.lng()});
			        }
			    });   
	}
    $.fn.overlayUserSpot = function(position){
    	
    	 userPosition = position;
    	 var userLat = position.latitude;
    	 var userLong = position.longitude;
    	 var latLng = new GLatLng(userLat, userLong);
    	 
    	 map.setCenter(latLng,15);
         map.setUIToDefault();
         
         var geocoder = new GClientGeocoder();
		 geocoder.getLocations(latLng,function(response){
		 
		 			if (!response || response.Status.code != 200) {
		 			   alert("Status Code:" + response.Status.code);
					} else {

				      var place = response.Placemark[0];
				      var info = '<b>This is where we think you are </b><br/>' + 		        		        
			        		   '<b>Address:</b>' + place.address + '<br>';
			          place = response.Placemark[0];
			          
			          
			          
			          var marker = $(markerMgr).createMarker({lat:userLat,lng:userLong,info:info,keyword:"user"});	        
				      map.addOverlay(marker);		    
				      marker.openInfoWindowHtml(info);    
					}
		 
		 
		 });
    	
    };
    
    $.fn.overlay4Marker = function(searchResults,iconURL,hideMarker,keyword)
	{		
		var markers = [];    		 
		

 		for (var i = 0; i < searchResults.length; i++) {
                        
      			var result = searchResults[i];   
      			
      			var existingMarker = $.fn.markerExist(result.lat,result.lng);
      			var markersByKeyword = $.fn.getMarkersByKeyword("foursquare");
      			
      			if(existingMarker == undefined || markersByKeyword == undefined){
      				
      				var markerIcon = $(markerMgr).createIcon(iconURL);
      				var marker = $(markerMgr).createMarker({lat: result.lat,lng: result.lng,info:result.html,icon:markerIcon,keyword:keyword});      				
      				map.addOverlay(marker); 
      				markers.push(marker);
      				
      				if(hideMarker)
      				{
      					marker.hide();
      				}
      			}      		

         	}

		return markers;
	};
	
    $.fn.overlayMarker = function(searchResults,iconURL,hideMarker,keyword)
	{		
		var markers = [];    		 
		

 		for (var i = 0; i < searchResults.length; i++) {
                        
      			var result = searchResults[i];   
      			
      			var existingMarker = $.fn.markerExist(result.lat,result.lng);
      			
      			if(existingMarker == undefined){
      				
      				var markerIcon = $(markerMgr).createIcon(iconURL);
      				var marker = $(markerMgr).createMarker({lat: result.lat,lng: result.lng,info:result.html.cloneNode(true),icon:markerIcon,keyword:keyword});      				
      				map.addOverlay(marker); 
      				markers.push(marker);
      				
      				if(hideMarker)
      				{
      					marker.hide();
      				}
      			}      		

         	}

		return markers;
	};
	
	$.fn.removeMarkerByKeyword = function(keyword){
		
		var markers = $(markerMgr).getMarkersByKeyword(keyword);			
		$.fn.removeMapMarker(markers);
		$(markerMgr).removeMarker(keyword);
		
	};
	
	$.fn.removeMapMarker = function(markers){
		
		jQuery.each(markers,function(index,marker){
			map.removeOverlay(marker);
		});
		
	}
       
}

function MarkerManager()
{
	var markersOnMap = new Object();
	var markerCheckBox;
	var keywordMarkers = new Object();
	
	$.fn.createMarker = function(params){
    
    	var lng = params.lng;
		var lat = params.lat;
		var info = params.info;
		var markerIcon = params.icon;
		var keyword = params.keyword;
		
		var markerLatLng = new google.maps.LatLng(lat,lng);		
		 	 	
		var marker = new google.maps.Marker(markerLatLng,{hide: false, icon: markerIcon});
		marker.bindInfoWindow(info);
		
		$.fn.addMarker(marker,info,keyword);
						
		return marker;
		
    };
    
    $.fn.removeMarker = function(keyword)
    {    	
    	jQuery.each(keywordMarkers[keyword], function(index,marker){
    		var key = $.fn.generateMarkerKey(marker.getLatLng());
        	delete markersOnMap[key];
    	});
    	
    	delete keywordMarkers[keyword];
    }
    $.fn.markerExist = function (lat,lng){
    	var markerLatLng = new google.maps.LatLng(lat,lng);	
    	var key = $.fn.generateMarkerKey(markerLatLng);
    	return markersOnMap[key];
    };
    
    $.fn.addMarker = function(marker,markerInfo,keyword){
    	
    	var gLatLng = marker.getLatLng();    	
    	var key = $.fn.generateMarkerKey(gLatLng);
    	markersOnMap[key] = {marker:marker,info:markerInfo};
    	
    	if(keywordMarkers[keyword] == undefined)
    	{
    		keywordMarkers[keyword] = [marker];
    	}else
    	{
    		keywordMarkers[keyword].push(marker);
    	}
    };
    
    $.fn.getMarkersByKeyword = function(keyword){
    	return keywordMarkers[keyword];
    };
    
    $.fn.getMarker = function(gLatLng){
    	var key = $.fn.generateMarkerKey(gLatLng);
    	console.log(markersOnMap[key]);
    	return markersOnMap[key];
    }
    
    $.fn.generateMarkerKey = function(gLatLng){
    	return "'" + gLatLng.lat() +"','" + gLatLng.lng() + "'";
    };
   
    
    $.fn.markerToggler = function(markers,markerToggler){
    
    	markerCheckBox = markerToggler;
    	
    	$(markerToggler).change(function(){
    	
    		jQuery.each(markers,function(index,marker){
				if(marker.isHidden()){
					marker.show();
				}else{
					marker.hide();
				}
			});
				
		});
    };
    
    $.fn.createIcon = function(iconURL){
		var baseIcon = new GIcon(G_DEFAULT_ICON);
		
		if(iconURL == undefined || $.trim(iconURL) == '')
		{
			return baseIcon;
		}
		
		var customIcon = new GIcon(baseIcon);
        customIcon.image = iconURL;
		customIcon.infoWindowAnchor = new GPoint(9,2);
		customIcon.iconSize = new GSize(32,32);
		
		return customIcon;
	};
    
}

function KeywordManager()
{
		var keywordMap = new Object();	
		
		
		keywordMap["Pharmacy"] = "img/Pharmacy-icon.png"; 	
	    keywordMap["Bank"] = "img/Bank-icon.png";
        keywordMap["Restaurant"] = "img/Restaurant-icon.png";
        
        $.fn.getIconURL = function(keyword){
        	var iconFileName = keywordMap[keyword];          	
        	return iconFileName;
        }
        
        $.fn.isExist = function(keyword){
        	return (keywordMap[keyword.toLowerCase()] !== undefined);        		
        }
        
        $.fn.addKeyword = function(keyword)
        {
        	keywordMap[keyword.toLowerCase()] = "";
        }
        
        $.fn.removeKeyword = function(keyword)
        {
        	delete keywordMap[keyword.toLowerCase()];
        }
        
	
}


function SearchManager(mapManager)
{
		var markerMgr = $(mapManager).getMarkerMgr();//new MarkerManager();
		var keywordMgr = new KeywordManager();
		
		$(mapManager).initUserMap();
		
		$.fn.searchFor = function (keyword){
		
			if($(keywordMgr).isExist(keyword))
			{
				var dialogMgr = new DialogManager();
				$(dialogMgr).showDialog({id:"searchWarn", height: "auto", width: "auto"});
				return;
			}
			
			$(keywordMgr).addKeyword(keyword);
			
			
			var searchBox = $.fn.createResultBox(keyword);
			var content = document.getElementById(searchBox.searchContentId);	
			var map = $(mapManager).getUserMap();
			var markerTogglerId= searchBox.searchCheckBoxId;				        
  			var localSearch = new google.search.LocalSearch();
  			
			localSearch.setCenterPoint(map);

			var searchControl = new google.search.SearchControl();
			var searchOptions = new google.search.SearcherOptions();
			searchOptions.setExpandMode(google.search.SearchControl.EXPAND_MODE_OPEN);
	
	  		searchControl.addSearcher(localSearch,searchOptions );
	  			  		
	  		searchControl.draw(content);
	  			  			  		
            searchControl.setSearchCompleteCallback (localSearch ,function(){
            
				var iconURL = $(keywordMgr).getIconURL(keyword);
				var dialogMgr = new DialogManager();
				
				var markerToggler = $("#" + markerTogglerId);
				var markers = $(mapManager).overlayMarker(localSearch.results,iconURL,!$(markerToggler).attr("checked"),keyword);
				$(markerMgr).markerToggler(markers,markerToggler);
				jQuery.each(localSearch.results,$.fn.setPan);				
				
				$(dialogMgr).setDraggable({
					searchBox: searchBox.searchBox
				});
				
				$(dialogMgr).minimizeAction({
					searchBox: searchBox.searchBox, 
					contentBox: searchBox.contentBox,
					minBtn: searchBox.minBtn});
				
				$(dialogMgr).maximizeAction({
					searchBox: searchBox.searchBox, 
					contentBox: searchBox.contentBox,
					maxBtn: searchBox.maxBtn});
				
				$(dialogMgr).closeAction({
					searchBox: searchBox.searchBox, 
					closeBtn: searchBox.closeBtn, 
					keyword: keyword,
					keywordMgr: keywordMgr,
					mapMgr:mapManager,
					markerMgr: markerMgr});
								     
				$("a[class='gs-title']").fancybox({
					 'width' : '90%',
					 'height' : '90%',
					 'autoScale' : false,
					 'transitionIn' : 'none',
					 'transitionOut' : 'none',
					 'type' : 'iframe'
				 }); 
				 
			});
            
            searchControl.execute(keyword);
            
		};
		
		$.fn.createResultBox = function(searchKeyword){
		
			
			
			var contentId = (searchKeyword + "Search").replace(' ','');
			var checkBoxId = (searchKeyword + "Marker").replace(' ','');
			var searchBoxId = (searchKeyword + "BoxId").replace(' ','');
	
			var searchBox = 
			"<div id='" + searchBoxId + "' title='" + searchKeyword + "' class='searchBox ui-dialog ui-widget ui-widget-content ui-corner-all  ui-draggable' role='dialog' aria-labelledby='ui-dialog-title-dialog'>"+
	  	  	"<div class='ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix' unselectable='on' style='-moz-user-select: none;'>" +
			"<span class='ui-dialog-title' id='ui-dialog-title-dialog' unselectable='on' style='-moz-user-select: none;'>" + searchKeyword + " near you </span>" +			
			"<a href='#' class='ui-dialog-titlebar-close ui-corner-all' role='button' unselectable='on' style='-moz-user-select: none; margin-right: 30px'>" + 
			"<span class='ui-icon ui-icon-minusthick' name='" + searchBoxId + "Min' unselectable='on' style='-moz-user-select: none;'></span>" +
			"</a>" +
			"<a href='#' class='ui-dialog-titlebar-close ui-corner-all' role='button' unselectable='on' style='-moz-user-select: none; margin-right: 15px'>" + 
			"<span class='ui-icon ui-icon-plusthick' name='" + searchBoxId + "Max' unselectable='on' style='-moz-user-select: none;'></span>" +
			"</a>" +
			"<a href='#' class='ui-dialog-titlebar-close ui-corner-all' role='button' unselectable='on' style='-moz-user-select: none;'>" + 
			"<span class='ui-icon ui-icon-closethick' name='" + searchBoxId + "Close' unselectable='on' style='-moz-user-select: none;'></span>" +
			"</a>" +
			"</div>" +		
			"<div id='" + contentId + "' class='contentBox ui-dialog-content ui-widget-content'></div>" +
			"<input id='" + checkBoxId + "' type='checkbox' checked='true'>show " + searchKeyword  + "</input><br/>" + 		
			"</div>";
			
			$("#searchContainer").prepend(searchBox);

					    						
			return {searchContentId: contentId, searchCheckBoxId: checkBoxId,searchBoxId: searchBoxId,
			        searchBox: $("#" + searchBoxId),
			        contentBox: $("#" + contentId),
				    minBtn:$("span[name='" + searchBoxId + "Min']"),
				    maxBtn:$("span[name='" + searchBoxId + "Max']"),
				    closeBtn:$("span[name='" + searchBoxId + "Close']")};
		};
		
		
		
		$.fn.setPan = function(index,result)
     	{
			var resultURL = result.url;
			var panToDIV = "<div id='" + result.lat + "' class='panTo' onClick=$.fn.PanTo(" + result.lat + "," +result.lng +")> Show on map </div>";
			
			var venueName = $("a[href='" + resultURL + "']").text();						
			var lat = result.lat;
			var lng = result.lng;
			
			var param = "onClick=$.fn.checkin('" + lat + "','" + lng + "','" + encodeURIComponent(venueName) + "')";			
			
			var checkinDIV = "<div class='panTo' " + param + " style='display:none'> Check in to foursquare </div>";
			$("a[href='" + resultURL + "']").after(panToDIV);
			$("a[href='" + resultURL + "']").after(checkinDIV);
			
						
			if( $.trim($("#foursquareLogin").text()).length == 0)
			{

				$(".panTo").show();
			}
		};
		
		$.fn.checkin = function(lat,lng,venueName)
		{
			
			$("#geolat").attr("value",lat);
			$("#geolong").attr("value",lng);
			$("#venueName").val(venueName);
			$("#foursquareForm").attr("action","checkin.do");
			$("#checkinMsg").text("Would you like to check in to " + decodeURIComponent(venueName) + " ? ");
			$("#checkin").show();
			
			
		
		}
        $.fn.PanTo = function(lat,lng)
    	{		
    		var gLatLng = new GLatLng(lat,lng);
    		var map = $(mapManager).getUserMap();
			map.panTo(gLatLng);
			
			var markerObj = $(markerMgr).getMarker(gLatLng);
			
			if(markerObj != undefined){
				var markerInfo = markerObj.info;
				markerObj.marker.openInfoWindowHtml(markerInfo);
			}
			
    	}
        
        $.fn.panToUserPos = function()
        {    	
        	var userPosition = $(mapManager).getUserPosition();
        	$.fn.PanTo(userPosition.latitude,userPosition.longitude);    			
        }
        
        
}

function DialogManager()
{
	
	$.fn.showDialog = function(params){
		
		var elementID = "#" + params.id;
		
		$(elementID).show();
		$(elementID).dialog("open");
		$(elementID).dialog({
			modal:true,
			height: params.height,
			width: params.width,
			modal: true,           
			buttons: { "Close": function() { $(this).dialog("destroy"); } },
			close: $.fn.close()
		});
		
		
	};
	
	$.fn.close = function(window)
	{
		$(window).dialog("destroy");
	}
	
	$.fn.setDraggable = function(dialog){
    	
    	$(dialog.searchBox).draggable({'handle' : '.ui-dialog-titlebar'});
    };
    
    
    $.fn.minimizeAction = function(dialog){
    	
    	var contentBoxOrginalHeight = $(dialog.contentBox).height();
		var searchBoxOriginalHeight = $(dialog.searchBox).height();
								
		$(dialog.minBtn).click(function(){
			$(dialog.contentBox).animate({height: 0},1000);
			$(dialog.searchBox).css("height","auto");
		});			
    }
            
    $.fn.maximizeAction = function(dialog){
    	
    	var contentBoxOrginalHeight = $(dialog.contentBox).height();
		var searchBoxOriginalHeight = $(dialog.searchBox).height();
						
		$(dialog.maxBtn).click(function(){
			$(dialog.contentBox).animate({height: contentBoxOrginalHeight},1000);
			$(dialog.searchBox).css("height",searchBoxOriginalHeight);
		});
    }
    
    $.fn.closeAction = function(dialog){
										   			   			
		$(dialog.closeBtn).click(function(){
			$(dialog.searchBox).remove();
			$(dialog.keywordMgr).removeKeyword(dialog.keyword);					
			$(dialog.mapMgr).removeMarkerByKeyword(dialog.keyword);
			
		});
		
	}
	
	
	
}
